/*
 *				MsgNFmt.c
 *
 * Prints a message in network format to blind target.
 */

/*
 *				history
 *
 * 89Apr27 HAW	Bad interaction of routemail and Other Recipients
 * 89Feb05 HAW  Created.
 */

#include "ctdl.h"

/*
 *				contents
 *
 *	prNetStyle()		sends a msg in net format.
 *	NetCC()			write out Other Recipient fields
 */

extern logBuffer logTmp;	/* Person buffer	*/
extern int	   callSlot;
extern NetBuffer netBuf;
extern SListBase MailForward;
extern CONFIG	cfg;	/* Lots an lots of variables	*/
extern MessageBuffer   msgBuf;

char   PrTransmit = TRUE;	/* TRUE if writing to comm line */
				/* FALSE if writing to disk	*/
static char Overrode;

void WriteField();
void NetCC();

#define CC		0
#define OVERRIDE	1
#define NONE		2

static char *GoingFor;
static int (*sm)(int c);
/*
 * prNetStyle()
 *
 * This sends a msg in NET format.  Target can be either disk or comm line.
 */
void prNetStyle(int NotMsgBase, int (*SourceFn)(void),
	int (*SendMethod)(int c), char GetMsg, char *TargetSystem)
{
	ForwardMail *address;
	long	val;
	extern char inNet;
	extern SListBase TempForward;

	GoingFor = TargetSystem;
	sm = SendMethod;

	/* fill in local node in origin fields if local message: */
	if (!msgBuf.mborig[ 0])
	strcpy(msgBuf.mborig,  cfg.nodeId + cfg.codeBuf  );
	if (!msgBuf.mboname[0]) {
		strcpy(msgBuf.mboname, cfg.nodeName + cfg.codeBuf);
		strcpy(msgBuf.mbdomain, cfg.nodeDomain + cfg.codeBuf);
	}

	/* Convert # to 8-bit Citadel style for compatibility   */
	if (!msgBuf.mbsrcId[0]) {
		val = atol(msgBuf.mbId);
		sprintf(msgBuf.mbsrcId, "%ld %ld",
				(val & 0xFFFF0000l) >> 16, val & 0xFFFFl);
	}

	/* send header fields out: */
	if (msgBuf.mbauth[ 0])
		if (!NetPrintf(sm, "A%s", msgBuf.mbauth )) return;
	if (msgBuf.mbdate[ 0])
		if (!NetPrintf(sm, "D%s", msgBuf.mbdate )) return;
	if (msgBuf.mbtime[ 0])
		if (!NetPrintf(sm, "C%s", msgBuf.mbtime )) return;
	if (!NetPrintf(sm, "N%s", msgBuf.mboname)) return;
	if (!NetPrintf(sm, "O%s", msgBuf.mborig )) return;
	if (msgBuf.mbdomain[0])
		if (!NetPrintf(sm, "X%s", msgBuf.mbdomain)) return;
	/* if (msgBuf.mbroom[ 0]) */
		if (!NetPrintf(sm, "R%s", msgBuf.mbroom )) return;
	if (!NetPrintf(sm, "S%s", msgBuf.mbsrcId)) return;
	if (msgBuf.mbOther[0])
		if (!NetPrintf(sm, "P%s", msgBuf.mbOther)) return;

	/* write out Who Else fields */
	RunListA(&msgBuf.mbCC, WriteField, (void *) CC);

	Overrode = FALSE;
	/*
	 * this if handles a piece of user-generated route mail
	 * in this situation there are no overrides and they must be
	 * generated from the mbCC list.
	 */
	if (!PrTransmit && inNet == NON_NET) {
		/*
		 * If mbOverride has stuff, this is caused by forwarding set up
		 * by one or more of the recipients of the mail.  This may
		 * include mail initially locally forwarded ...
		 */
		if (GetFirst(/* &msgBuf.mbInternal */ &TempForward) == NULL) {
			RunList(&msgBuf.mbCC, NetCC);
		}
		else {
			RunList(/* &msgBuf.mbInternal */ &TempForward, NetCC);
		}
	}
	/*
	 * this else translates to route mail being written to disk caused by
	 * mail forwarding during a network session -- that's the only case
	 * that'll satisfy this if. In this case the only override generation
	 * can come from the overrides already in place -- they are the only
	 * recipients on this system, so only they can generate a mail
	 * forwarding request.
	 */
	else if (!PrTransmit && inNet != NON_NET) {
		RunList(&msgBuf.mbOverride, NetCC);
		RunList(&msgBuf.mbInternal, NetCC);
	}
	/*
	 * this else translates to network transmission of "normal" mail --
	 * that is, mail coming from the message base and therefore not
	 * bearing overrides.  Any overrides must therefore be generated
	 * from the Who Else list.
	 */
	else if (!NotMsgBase && PrTransmit && inNet != NON_NET) {
		RunList(&msgBuf.mbCC, NetCC);
	}

	/*
	 * this else covers route mail about to be transmitted on the net.
	 * In this case the override fields already exist (from the originating
	 * system) so we just write them out, and everything's cool.
	 */
	else if (NotMsgBase && PrTransmit && inNet != NON_NET) {
		RunListA(&msgBuf.mbOverride, WriteField, (void *) OVERRIDE);
	}

	if (msgBuf.mbaddr[ 0] && (!PrTransmit || Overrode)) {
		if (!NetPrintf(sm, "Q%s", msgBuf.mbaddr )) return;
	}

	/*
	 * Basically, only do possible 'T' transformations if we're not outgoing
	 * route mail and we're not writing route mail to disk generated by
	 * incoming mail hitting a person with mail forwarding on.
	 */
	if (!(NotMsgBase && PrTransmit && inNet != NON_NET)) {
		/*
		 * we use this control structure for backward compatability:
		 * systems which do not recognize the 'w' field of net messages.
		 */
		if (Overrode) {
			if (msgBuf.mbto[  0])
				if (!NetPrintf(sm, "T%s", msgBuf.mbto   ))
					return;

			if (SearchList(&msgBuf.mbInternal,msgBuf.mbto)==NULL) {
				if (msgBuf.mbaddr[0])
					sprintf(msgBuf.mbtext, "%s@%s",
						msgBuf.mbto, msgBuf.mbaddr);
				else
					strcpy(msgBuf.mbtext, msgBuf.mbto);

				NetCC(msgBuf.mbtext);
			}
		}
		else {
			if (msgBuf.mbto[   0]) {
				address = SearchList(&MailForward, msgBuf.mbto);
				if (!NetPrintf(sm, "T%s",
					(address != NULL &&
					strCmpU(address->System, GoingFor)
					== SAMESTRING) ? address->Alias :
						msgBuf.mbto))
					return;
			}
			else if (!NetPrintf(sm, "T%s", msgBuf.mbto)) return;
		}
	}
	else if (msgBuf.mbto[0]) if (!NetPrintf(sm, "T%s", msgBuf.mbto)) return;

	RunListA(&msgBuf.mbForeign, WriteField, (void *) NONE);

	/* send message text proper: */
	if (GetMsg) {
		getMsgStr(SourceFn, msgBuf.mbtext, MAXTEXT);
	}
	if (!NetPrintf(sm, "M%s", msgBuf.mbtext)) return;
}

/*
 * NetCC()
 *
 * This function is used to write out Other Recipient fields and sometimes
 * to write override fields (only when system origin is this system, not
 * another, however).
 */
static void NetCC(char *d)
{
	ForwardMail *address;
	label person;
	char  system[(2 * NAMESIZE) + 2];
	NetBuffer locnet;

	initNetBuf(&locnet);
	switch (SepNameSystem(d, person, system, &locnet)) {
	case IS_SYSTEM:
		if (strCmpU(system, GoingFor) == SAMESTRING ||
			strCmpU(LocalName(system), GoingFor) == SAMESTRING) {
			Overrode = TRUE;
			NetPrintf(sm, "w%s", person);
		}
		break;
	case NOT_SYSTEM:	/* forward to this system??? */
		if ((address = SearchList(&MailForward, person)) != NULL &&
			strCmpU(address->System, GoingFor) == SAMESTRING) {
			Overrode = TRUE;
			NetPrintf(sm, "w%s", address->Alias);
		}
		break;
	}
	killNetBuf(&locnet);
}

static void WriteField(char *d, int FieldType)
{
	NetPrintf(sm, (FieldType == OVERRIDE) ? "w%s" :
					(FieldType == CC) ? "W%s" : "%s", d);
}
